gusucode.com > 各种VC自绘控件源码程序 > 各种VC自绘控件源码/code/SkinControls(自绘MFC基本控件 )/SkinControls/SkinControls/SkinListCtrl.cpp

    
#include "stdafx.h"
#include "Resource.h"
#include "SkinListCtrl.h"
#include "MemDC.h"

//////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CSkinListCtrl, CListCtrl)

BEGIN_MESSAGE_MAP(CSkinHeaderCtrl, CHeaderCtrl)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONUP()
	ON_WM_RBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(HDM_LAYOUT, OnLayout) 
END_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(CSkinListCtrl, CListCtrl)
	ON_WM_CREATE()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_WM_MEASUREITEM_REFLECT()
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////////


//默认属性
//#define LIST_STYTE					LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_ONECLICKACTIVATE|LVS_EX_UNDERLINEHOT|LVS_EX_FLATSB
#define LIST_STYTE					LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP

//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////

//构造函数
CSkinHeaderCtrl::CSkinHeaderCtrl()
{
	m_iSortCol=-1;
	m_SortType=Type_NoSort;
	m_pIHeaderCtrlSink=NULL;
	m_bEnableDrag = true;
	m_nHeadHeight = 25;
}

//析构函数
CSkinHeaderCtrl::~CSkinHeaderCtrl()
{
}

//重画函数
void CSkinHeaderCtrl::OnPaint() 
{
	//获取位置
	CRect ClientRect;
	GetClientRect(&ClientRect);

	//设置自画
	HD_ITEM HDItem;
	HDItem.mask=HDI_FORMAT;
	int iItemCount=GetItemCount();
	for (int i=0;i<iItemCount;i++)
	{
		GetItem(i,&HDItem);
		HDItem.fmt|=HDF_OWNERDRAW;
		SetItem(i,&HDItem);
	}

	//建立缓冲图
	CBitmap BufferBmp;
	CClientDC ClientDC(this);
	BufferBmp.CreateCompatibleBitmap(&ClientDC,ClientRect.Width(),ClientRect.Height());
	m_BufferDC.CreateCompatibleDC(&ClientDC);
	m_BufferDC.SelectObject(&BufferBmp);
	m_BufferDC.SetBkMode(TRANSPARENT);

	//加载位图
	if (m_ImageHead.IsValid())
	{
		m_ImageHead.Draw(m_BufferDC.m_hDC, ClientRect);
	}
	else
	{
		m_BufferDC.FillSolidRect(&ClientRect, RGB(255,255,255));
	}

	if (m_ImageSeparator.IsValid())
	{
		m_ImageSeparator.Draw(m_BufferDC.m_hDC, ClientRect.right-2, (ClientRect.Height()-m_ImageSeparator.GetHeight())/2);
	}
	else
	{
		CPen pen,pen1;
		pen.CreatePen(PS_SOLID, 1, RGB(62,178,226));
		m_BufferDC.SelectObject(&pen);
		m_BufferDC.MoveTo(ClientRect.right-1, 6);
		m_BufferDC.LineTo(ClientRect.right-1, 20);
		pen1.CreatePen(PS_SOLID, 1, RGB(62,178,226));
		m_BufferDC.SelectObject(&pen1);
		m_BufferDC.MoveTo(ClientRect.left, ClientRect.bottom-1);
		m_BufferDC.LineTo(ClientRect.right, ClientRect.bottom-1);
	}

	Default();
	
	//绘画界面
	ClientDC.BitBlt(0,0,ClientRect.Width(),ClientRect.Height(),&m_BufferDC,0,0,SRCCOPY);
	m_BufferDC.DeleteDC();
	BufferBmp.DeleteObject();
	
	return;
}

LRESULT CSkinHeaderCtrl::OnLayout(WPARAM wParam, LPARAM lParam)
{
	LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, wParam, lParam);

	HDLAYOUT& hdLayout = *reinterpret_cast<LPHDLAYOUT>(lParam);
	LPRECT lpRect = hdLayout.prc;
	LPWINDOWPOS lpWindowPos = hdLayout.pwpos;

	lpRect->top = lpWindowPos->cy = m_nHeadHeight;

	return lResult;
}

void CSkinHeaderCtrl::SetHeaderImage(LPCTSTR pszFileName, DWORD imagetype)
{
	m_ImageHead.Load(pszFileName,imagetype);
	if (m_ImageHead.IsValid())
	{
		m_nHeadHeight = m_ImageHead.GetHeight();
	}
}

void CSkinHeaderCtrl::SetSeparatorImage(LPCTSTR pszFileName, DWORD imagetype)
{
	m_ImageSeparator.Load(pszFileName,imagetype);
}

//绘画函数
void CSkinHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	//获取 DC
	CDC * pDC=NULL;
	if (m_BufferDC.GetSafeHdc()==NULL)
	{
		pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
		pDC->SetBkMode(TRANSPARENT);
	}
	else pDC=&m_BufferDC;

	CRect rc(lpDrawItemStruct->rcItem);

	//获取信息
	HDITEM HDItem;
	TCHAR szBuffer[64];
	HDItem.pszText=szBuffer;
	HDItem.mask=HDI_TEXT|HDI_FORMAT;
	HDItem.cchTextMax=sizeof(szBuffer)/sizeof(szBuffer[0]);
	CRect rcItemRect=lpDrawItemStruct->rcItem;
	GetItem(lpDrawItemStruct->itemID,&HDItem);

	//获取状态
	bool bSelected=(lpDrawItemStruct->itemState==ODS_SELECTED);

	//绘画背景
	if (m_ImageHead.IsValid())
	{
		m_ImageHead.Draw(pDC->m_hDC, rcItemRect);
	}
	else
		pDC->FillSolidRect(&rcItemRect, RGB(255,255,255));

	if (m_ImageSeparator.IsValid())
	{
		m_ImageSeparator.Draw(pDC->m_hDC, rcItemRect.right-2, (rcItemRect.Height()-m_ImageSeparator.GetHeight())/2);
	}
	else
	{
		CPen pen,pen1;
		pen.CreatePen(PS_SOLID, 1, RGB(62,178,226));
		pDC->SelectObject(&pen);
		pDC->MoveTo(rcItemRect.right-1, 6);
		pDC->LineTo(rcItemRect.right-1, 20);
		pen1.CreatePen(PS_SOLID, 1, RGB(62,178,226));
		pDC->SelectObject(&pen1);
		pDC->MoveTo(rcItemRect.left, rcItemRect.bottom-1);
		pDC->LineTo(rcItemRect.right, rcItemRect.bottom-1);
	}
	rcItemRect.DeflateRect(5,0,5,0);

	//绘画标志
	if ((m_iSortCol==lpDrawItemStruct->itemID)&&(m_SortType!=Type_NoSort))
	{
		if (rcItemRect.Width()>=14)
		{
			int nXOff=0,nYPos=(rcItemRect.Height()-9)/2+rcItemRect.top;
			if (bSelected) { nYPos++; nXOff++; }
			CPen * pWhitePen=CPen::FromHandle((HPEN)GetStockObject(WHITE_PEN));
			CPen * pBlackPen=CPen::FromHandle((HPEN)GetStockObject(BLACK_PEN));
			if (m_SortType==Type_Ascend)
			{
				pDC->SelectObject(pWhitePen);
				pDC->MoveTo(rcItemRect.right-5+nXOff,nYPos);
				pDC->LineTo(rcItemRect.right-14+nXOff,nYPos);
				pDC->LineTo(rcItemRect.right-10+nXOff,nYPos+9);
				pDC->SelectObject(pBlackPen);
				pDC->LineTo(rcItemRect.right-5+nXOff,nYPos);
			}
			else
			{
				pDC->SelectObject(pWhitePen);
				pDC->MoveTo(rcItemRect.right-10+nXOff,nYPos);
				pDC->LineTo(rcItemRect.right-14+nXOff,nYPos+9);
				pDC->LineTo(rcItemRect.right-5+nXOff,nYPos+9);
				pDC->SelectObject(pBlackPen);
				pDC->LineTo(rcItemRect.right-10+nXOff,nYPos);
			}
		}
		rcItemRect.right-=19;
	}

	//绘画标题字体
	UINT uFormat=DT_WORDBREAK|DT_EDITCONTROL|DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER;
	CFont font;
	font.CreateFont(-12,0,0,0,400,0,0,0,134,3,2,1,2,TEXT("宋体"));
	pDC->SelectObject(&font);
	if (bSelected) rcItemRect.OffsetRect(1,1);
	pDC->DrawText(HDItem.pszText,lstrlen(HDItem.pszText),&rcItemRect,uFormat|DT_CENTER);

	return;
}

//背景函数
BOOL CSkinHeaderCtrl::OnEraseBkgnd(CDC * pDC) 
{
	return TRUE;
}

//获取标题
LPCTSTR CSkinHeaderCtrl::GetItemText(int iCol, TCHAR szBuffer[], int nSize)
{
	ASSERT(szBuffer!=NULL);
	if (iCol<GetItemCount())
	{
		HDITEM HDItem;
		HDItem.pszText=szBuffer;
		HDItem.mask=HDI_TEXT;
		HDItem.cchTextMax=nSize;
		GetItem(iCol,&HDItem);
	}
	else szBuffer[0]=0;
	return szBuffer;
}

//坐标转换
int CSkinHeaderCtrl::PointToColIndex(CPoint Point)
{
	CRect rcItemRect;
	int iItemCount=GetItemCount();
	for (int i=0;i<iItemCount;i++)
	{
		GetItemRect(i,&rcItemRect);
		if (rcItemRect.PtInRect(Point)) return i;
	}
	return -1;
}

//设置标志
void CSkinHeaderCtrl::SetSortArrow(int iSortCol, enHeaderSortType SortType)
{
	m_iSortCol=iSortCol;
	m_SortType=SortType;
	Invalidate(FALSE);
	return;
}

//获取标志
void CSkinHeaderCtrl::GetSortArrow(int & iSortCol, enHeaderSortType & SortType)
{
	iSortCol=m_iSortCol;
	SortType=m_SortType;
	return;
}

//鼠标消息
void CSkinHeaderCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	if (m_pIHeaderCtrlSink!=NULL) m_pIHeaderCtrlSink->OnHeaderLButtonDown(this,nFlags,point);
	if (m_bEnableDrag) CHeaderCtrl::OnLButtonDown(nFlags, point);
	else return;
}

//鼠标消息
void CSkinHeaderCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
	if (m_pIHeaderCtrlSink!=NULL) m_pIHeaderCtrlSink->OnHeaderLButtonUp(this,nFlags,point);
	if (m_bEnableDrag) CHeaderCtrl::OnLButtonUp(nFlags, point);
	else return;
}

//鼠标消息
void CSkinHeaderCtrl::OnRButtonUp(UINT nFlags, CPoint point)
{
	if (m_pIHeaderCtrlSink!=NULL) m_pIHeaderCtrlSink->OnHeaderRButtonUp(this,nFlags,point);
	CHeaderCtrl::OnRButtonUp(nFlags, point);
}

//鼠标消息
void CSkinHeaderCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
	if (m_pIHeaderCtrlSink!=NULL) m_pIHeaderCtrlSink->OnHeaderRButtonDown(this,nFlags,point);
	CHeaderCtrl::OnRButtonDown(nFlags, point);
}

void CSkinHeaderCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
	if (m_bEnableDrag) CHeaderCtrl::OnMouseMove(nFlags, point);
	else return;
}

//////////////////////////////////////////////////////////////////////////

//构造函数
CSkinListCtrl::CSkinListCtrl()
{
	m_nMoveItem = -1;
}

//析构函数
CSkinListCtrl::~CSkinListCtrl()
{
}

//控件绑定
void CSkinListCtrl::PreSubclassWindow()
{
	__super::PreSubclassWindow();
	m_SkinHeadCtrl.SubclassWindow(GetHeaderCtrl()->GetSafeHwnd());
	SetExtendedStyle(LIST_STYTE);
	return;
}

//建立消息
int CSkinListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (__super::OnCreate(lpCreateStruct)==-1) return -1;
	m_SkinHeadCtrl.SubclassWindow(GetHeaderCtrl()->GetSafeHwnd());
	SetExtendedStyle(LIST_STYTE);
	return 0;
}

void CSkinListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CRect rcItem=lpDrawItemStruct->rcItem;
	CDC * pDC=CDC::FromHandle(lpDrawItemStruct->hDC);

	int iItem=lpDrawItemStruct->itemID;
	int iCount=GetHeaderCtrl()->GetItemCount();
	int iBeen=rcItem.left;
	TCHAR szBuffer[1024];
	CFont font;
	font.CreateFont(-12,0,0,0,400,0,0,0,134,3,2,1,2,TEXT("宋体"));
	pDC->SelectObject(&font);

	GetItemRect(iItem, rcItem, LVIR_LABEL);

	for (int i=0;i<iCount;i++)
	{
		CRect rcSubItem;
		int iWidth=GetColumnWidth(i);

		GetSubItemRect(iItem,i,LVIR_LABEL,rcSubItem);
		if (lpDrawItemStruct->itemState&ODS_FOCUS) pDC->FillSolidRect(&rcSubItem,RGB(40,82,144)); 
		else if (m_nMoveItem == iItem) pDC->FillSolidRect(&rcSubItem,RGB(194,255,246)); 
		else pDC->FillSolidRect(&rcSubItem,GetBkColor());

		GetItemText(iItem,i,szBuffer,sizeof(szBuffer));
		rcSubItem.left+=3;

		pDC->DrawText(szBuffer,lstrlen(szBuffer),rcSubItem,DT_LEFT|DT_VCENTER|DT_END_ELLIPSIS|DT_SINGLELINE);
	}


	return;
}


void CSkinListCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
	LVHITTESTINFO lht;
	lht.pt = point;
	lht.flags = LVHT_ABOVE;

	int nItem = SubItemHitTest(&lht);
	if(m_nMoveItem != nItem)
	{
		CRect rc;
		if (m_nMoveItem != -1)
			GetItemRect(m_nMoveItem, &rc,LVIR_BOUNDS);
		m_nMoveItem = lht.iItem;
		InvalidateRect(&rc, FALSE);
		if (m_nMoveItem != -1)
			GetItemRect(m_nMoveItem, &rc,LVIR_BOUNDS);
		InvalidateRect(&rc, FALSE);
	}

	return __super::OnMouseMove(nFlags, point);

}


//绘画背景
BOOL CSkinListCtrl::OnEraseBkgnd(CDC * pDC)
{
	if (m_SkinHeadCtrl.GetSafeHwnd())
	{
		CRect ClientRect,ListHeaderRect;
		GetClientRect(&ClientRect);
		m_SkinHeadCtrl.GetWindowRect(&ListHeaderRect);
		ClientRect.top=ListHeaderRect.Height();
		pDC->FillSolidRect(&ClientRect,GetBkColor());
		return TRUE;
	}
	return __super::OnEraseBkgnd(pDC);
}

void CSkinListCtrl::MeasureItem(LPMEASUREITEMSTRUCT   lpMeasureItemStruct) 
{ 
	lpMeasureItemStruct-> itemHeight   =   20;   //这个就是你要设置的高度
} 


//////////////////////////////////////////////////////////////////////////